/*
 * @Author: yuluoY 2120942398@qq.com
 * @Date: 2024-10-28 20:53:25
 * @LastEditors: yuluoY 2120942398@qq.com
 * @LastEditTime: 2024-11-03 16:27:16
 * @FilePath: \Projecte:\gitee\GD32F427\gd32-f427\App\src\app_key.c
 * @Description: 
 * 
 * Copyright (c) 2024 by ${YuluoY}, All Rights Reserved. 
 */
#include "app_key.h"

key_dev_t key0_info;
key_dev_t key1_info;

/* 按键状态机状态 */
enum eKeyStatus
{
	KEY_INIT = 0,	    /* 按键初始化状态 */
	KEY_DITHER,	        /* 按键去抖状态 */
	KEY_CONFIRM, 	    /* 按键确认状态 */
	KEY_RELEASE,        /* 按键释放状态 */
} eKeySta;

/* 按键键值 */
enum eKeyValue
{
	key0 = 0x01,		 /* Key0 value */
	key1 = 0x02, 		 /* Key1 value */
    key2 = 0x04,        /* Key2 value */
}eKeyVal;

uKeyPress_t uKeyPress;
uKeyHold_t uKeyHold;
uKeyRelease_t uKeyRelease;
uKey4Continue_t uKeyContinue;
key_info_t sKey0, sKey1, sKey2;

/**
 * @Author: YuluoY
 * @Date: 2024-10-31 21:15:24
 * @LastEditors: yuluoY 2120942398@qq.com
 * @LastEditTime: Do not edit
 * @Description: key创建函数
 * @return {}
 */
void app_key_create(void)
{
    drv_key_info_init(&key0_info, RCU_GPIOE, GPIOE, GPIO_PIN_4, GPIO_PUPD_PULLDOWN);
    drv_key_info_init(&key1_info, RCU_GPIOA, GPIOA, GPIO_PIN_0, GPIO_PUPD_PULLDOWN);

    drv_key_init(&key0_info);
    drv_key_init(&key1_info);

    app_key_clr();

    app_key_setmode(FUNC_SHORT_LONG, &sKey0);
    app_key_setmode(FUNC_SHORT_CONTINUE, &sKey1);
    app_key_setmode(FUNC_LONG, &sKey2);
}

/**
 * @Author: YuluoY
 * @Date: 2024-11-01 20:49:36
 * @LastEditors: yuluoY 2120942398@qq.com
 * @LastEditTime: Do not edit
 * @Description: 读取按键键值
 * @return {}
 */
uint8_t app_key_readval(void)
{
    uint8_t l_keydata = 0;

    if(drv_key_readbit(&key0_info)) l_keydata |= key0;
    if(drv_key_readbit(&key1_info)) l_keydata |= key1;
    if(touch_in_image(lcddev.width - 80, lcddev.height - 80, lcddev.width - 16, lcddev.height - 16)) l_keydata |= key2;

    return l_keydata;
}

/**
 * @Author: YuluoY
 * @Date: 2024-11-01 21:21:24
 * @LastEditors: yuluoY 2120942398@qq.com
 * @LastEditTime: Do not edit
 * @Description: 按键扫描任务
 * @return {}
 */
void key_task(void)
{
    uint8_t l_keydata;
    l_keydata = app_key_readval();
    app_key_scanf(l_keydata & key0, &sKey0);
    app_key_scanf(l_keydata & key1, &sKey1);
    app_key_scanf(l_keydata & key2, &sKey2);
}

/**
 * @Author: YuluoY
 * @Date: 2024-11-01 21:17:55
 * @LastEditors: yuluoY 2120942398@qq.com
 * @LastEditTime: Do not edit
 * @Description: 按键扫描函数
 * @param {uint8_t} l_keydata
 * @param {key_info_t} *key
 * @return {}
 */
void app_key_scanf(uint8_t l_keydata, key_info_t *key)
{
    switch (key->Key_Status)
    {
    case KEY_INIT:                                                                                  /* 按键等待状态 */
        if(l_keydata)                                                                               /* 有按键按下 */
        {
            key->Key_Hold_count = 0;                                                                /* 先将计数器清零 */
            key->Key_Value = l_keydata;                                                             /* 给键值赋值 */
            key->Key_Status = KEY_DITHER;                                                           /* 转入按键消抖状态 */
        }
        break;
    
    case KEY_DITHER:                                                                                /* 按键消抖状态 */
        if(key->Key_Value == l_keydata)                                                             /* 按键还是按下 */
        {
            key->Key_Hold_count ++;                                                                 /* 按键按下时间计数 */
            if(key->Key_Hold_count > BTN_DITHER)                                                    /* 大于消抖时间，则按键按下 */
            {
                uKeyPress.KeyPress_Flag |= l_keydata;                                               /* 按下标志位置位 */
                key->Key_Status = KEY_CONFIRM;                                                      /* 转入按键确认状态 */
            }
        }
        else                                                                                        /* 按键松开了 */
        {
            key->Key_Value = KEY_INIT;                                                              /* 回到按键等待状态 */
        }
        break;

    case KEY_CONFIRM:                                                                               /* 按键确认状态 */
        if(key->Key_Value == l_keydata)                                                             /* 按键还是按下 */
        {
            if(key->Key_Hold_count < 0xFE)                                                          /* 防止超出最大计数值后溢出变0 */
            {
                key->Key_Hold_count ++;                                                             /* 计数器计数 */
            }
            if(key->Key_Hold_count > key->Key_longpress_time)                                       /* 大于长按的时间了 */
            {
                uKeyHold.KeyHold_Flag |= l_keydata;                                                 /* 长按标志位置位 */
                if(key->KeyFunc & ENABLE_CONTINUE_FUNC)                                             /* 如果使能了连按 */
                {
                    uKeyContinue.KeyContinue_Flag |= l_keydata;                                     /* 连按标志位置位 */
                    key->Key_Hold_count = key->Key_longpress_time - BTN_CONTINUE_PRESS_INTERVAL;    /* 设定的长按时间 - 连按的时间间隔，为下一次按下做准备*/
                }
            }
        }
        else                                                                                        /* 按键松开了 */
        {
            key->Key_Status = KEY_RELEASE;                                                          /* 跳转到按键释放状态 */
        }
        break;

    case KEY_RELEASE:                                                                               /* 按键释放状态 */
        if(!l_keydata)                                                                              /* 没有按键是按下的状态 */
        {
            uKeyHold.KeyHold_Flag &= ~key->Key_Value;                                               /* 按键信息清除时，注意有可能是两个按键按下，释放其中一个；所以要按位去清除 */
            uKeyPress.KeyPress_Flag &= ~key->Key_Value;
            uKeyContinue.KeyContinue_Flag &= ~key->Key_Value;
            uKeyRelease.KeyRelease_Flag |= key->Key_Value;
            key->Key_Status = KEY_INIT;
        }
        break;

    default:
        break;
    }
}

/**
 * @Author: YuluoY
 * @Date: 2024-11-01 21:31:06
 * @LastEditors: yuluoY 2120942398@qq.com
 * @LastEditTime: Do not edit
 * @Description: 设置按键功能
 * @param {uint8_t} function
 * @param {key_info_t} *key
 * @return {}
 */
void app_key_setmode(uint8_t function, key_info_t *key)
{
    switch (function)
    {
    case FUNC_SHORT:
        key->KeyFunc &= ~ENABLE_CONTINUE_FUNC;
        key->Key_longpress_time = BTN_INVALID;
        break;

    case FUNC_SHORT_LONG:
        key->KeyFunc &= ~ENABLE_CONTINUE_FUNC;
        key->Key_longpress_time = BTN_LONG_PRESS;
        break;

    case FUNC_LONG:
        key->KeyFunc &= ~ENABLE_CONTINUE_FUNC;
        key->Key_longpress_time = BTN_SUPER_LONG_PRESS;
        break;

    case FUNC_SHORT_CONTINUE:
        key->KeyFunc |= ENABLE_CONTINUE_FUNC;
        key->Key_longpress_time = BTB_CONTINUE_PRESS_TIME;
        break;
    
    default:
        key->KeyFunc &= ~ENABLE_CONTINUE_FUNC;
        key->Key_longpress_time = BTN_SUPER_LONG_PRESS;
        break;
    }
}

/**
 * @Author: YuluoY
 * @Date: 2024-11-01 21:25:41
 * @LastEditors: yuluoY 2120942398@qq.com
 * @LastEditTime: Do not edit
 * @Description: 部分按键信息清除
 * @return {}
 */
void app_key_clr(void)
{
    uKeyHold.KeyHold_Flag = 0;
    uKeyPress.KeyPress_Flag = 0;
    uKeyRelease.KeyRelease_Flag = 0;
    uKeyContinue.KeyContinue_Flag = 0;

    sKey0.Key_Value = 0;
    sKey1.Key_Value = 0;

    sKey0.Key_Status = 0;
    sKey1.Key_Status = 0;
}

